package com.howcode.aqchat.handler;


import com.howcode.aqchat.holder.GlobalChannelHolder;
import com.howcode.aqchat.service.service.ITokenHolder;
import io.netty.channel.ChannelHandler;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelInboundHandlerAdapter;
import io.netty.channel.socket.nio.NioSocketChannel;
import io.netty.handler.codec.http.*;
import io.netty.util.AttributeKey;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.stereotype.Component;

/**
 * @Author: ZhangWeinan
 * @Description: 心跳处理器
 * @date 2024-04-21 22:23
 */
@Slf4j
@Component
@ChannelHandler.Sharable
public class ChannelAuthHandler extends ChannelInboundHandlerAdapter implements InitializingBean {

    private static final Logger Logger = LoggerFactory.getLogger(ChannelAuthHandler.class);

    @Resource
    private GlobalChannelHolder channelHolder;

    @Resource
    private ITokenHolder tokenHolder;

    @Override
    public void userEventTriggered(ChannelHandlerContext ctx, Object evt) throws Exception {
        if (evt instanceof FullHttpRequest request) {
            // 获取请求头中的身份验证令牌
            HttpHeaders headers = request.headers();
            if (headers.isEmpty()) {
                ctx.channel().close();
                return;
            }
            String token = headers.get("auth-token");
            String userId = headers.get("auth-user-id");
            if (StringUtils.isEmpty(token) || StringUtils.isEmpty(userId) || !tokenHolder.checkToken(userId, token)) {
                refuseChannel(ctx);
                return;
            }

            //TODO 校验ticket
            // 将用户ID作为自定义属性加入到channel中，方便随时channel中获取用户ID
            AttributeKey<String> key = AttributeKey.valueOf("userId");
            ctx.channel().attr(key).setIfAbsent(userId);
             //关联channel
            channelHolder.put(userId,(NioSocketChannel) ctx.channel());

            ctx.pipeline().remove(this);
            // 对事件进行传播，知道完成WebSocket连接。
            ctx.fireChannelRead(evt);
        } else {
            ctx.channel().close();
        }
    }

    @Override
    public void afterPropertiesSet() throws Exception {
        Logger.info("HearBeatHandler init Success");
    }

    private void refuseChannel(ChannelHandlerContext ctx) {
        ctx.channel().writeAndFlush(new DefaultFullHttpResponse(HttpVersion.HTTP_1_1, HttpResponseStatus.UNAUTHORIZED));
        ctx.channel().close();
    }
}
